package com.ruoyi.framework.web.service;


import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.domain.model.RegisterBody;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.security.context.AuthenticationContextHolder;
import com.ruoyi.system.domain.LoginParams;
import com.ruoyi.system.domain.Student;
import com.ruoyi.system.domain.SysUserCid;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.domain.utils.SMSUtils;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.ISysPostService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 移动端登录服务接口
 */
@Component
public class MobileLoginService  {

    private static final Logger log = LoggerFactory.getLogger(MobileLoginService.class);

    @Autowired(required = false)
    private TokenService tokenService;

    @Autowired(required = false)
    private SysLoginService sysLoginService;

    @Autowired(required = false)
    private ISysRoleService sysRoleService;

    @Autowired(required = false)
    private AuthenticationManager authenticationManager;

    @Autowired(required = false)
    private ISysUserService sysUserService;

/*    @Autowired(required = false)
    private PermissionService permissionService;*/

    @Autowired
    private SysPermissionService permissionService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private SysUserCidMapper sysUserCidMapper;
    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private SysTeacherUserMapper sysTeacherUserMapper;
    /**
     * 注入redis服务
     */
    @Autowired(required = false)
    private RedisCache redisCache;

    /**
     * 请求时间戳过期时间5分钟
     */
    private static final int REQUEST_TIME_OUT = 1000 * 60 * 5;


    /**
     * jwt密钥
     */
    @Value("${token.secret}")
    private String jwtSecretKey;

    public AjaxResult login(LoginParams loginParams) {
        log.debug("login and loginParams:{}", loginParams);

        if (Objects.isNull(loginParams)) {
            return AjaxResult.error(-6,"登录参数不能为空");
        }
        String loginType = loginParams.getLoginType();
        if(StringUtils.isBlank(loginType)){
            return AjaxResult.error(-6,"登录方式不能为空");
        }
        // 用户验证
        Authentication authentication = null;
        //登录方式0验证码登录，1用户名密码登录，2本机一键登录，3微信单点登录
        if(loginType.equals("0")){
            String codeKey= CacheConstants.PHONE_LOGIN_CODE_KEY+loginParams.getPhoneNo();
            String codeSession =(String) redisCache.getCacheObject(codeKey);
            //从session中获得保存到的验证码
            String validCode = loginParams.getValidCode();
            if (StringUtils.isBlank(validCode)) {
                return AjaxResult.error(-6,"验证码不能为空");
            }
            if (!codeSession.equals(validCode)) {
                return AjaxResult.error(-6,"验证码错误");
            }
            try
            {
                SysUser sysUser = userService.selectUserByUserName(loginParams.getUsername());
                UserDetails userDetails=new LoginUser(sysUser.getUserId(), sysUser.getDeptId(), sysUser, permissionService.getMenuPermission(sysUser));
                authentication = new UsernamePasswordAuthenticationToken(userDetails, null,
                        AuthorityUtils.createAuthorityList("ROLE_USER"));
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
            catch (Exception e)
            {
                if (e instanceof BadCredentialsException)
                {
                    AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginParams.getUsername(), Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                    throw new UserPasswordNotMatchException();
                }
                else
                {
                    AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginParams.getUsername(), Constants.LOGIN_FAIL, e.getMessage()));
                    throw new ServiceException(e.getMessage());
                }
            }


//            String phoneNo = loginParams.getPhoneNo();
//            if(StringUtils.isBlank(phoneNo)){
//                return AjaxResult.error(-6,"登录名不能为空");
//            }
//            String validCode = loginParams.getValidCode();
            //2表示登录验证码，校验验证码合法性
            //sysSmsSendService.checkValidCode(phoneNo,validCode,"2");
//            loginParams.setUsername(phoneNo);

//            loginParams.setPassword(loginParams.getPassword());
        }else if(loginType.equals("1")){
            String password = loginParams.getPassword();
            if(StringUtils.isBlank(password)){
                return AjaxResult.error(-6,"密码不能为空");
            }

            try
            {
                UsernamePasswordAuthenticationToken authenticationToken=new UsernamePasswordAuthenticationToken(loginParams.getUsername(), loginParams.getPassword());
                AuthenticationContextHolder.setContext(authenticationToken);
                authentication = authenticationManager
                        .authenticate(new UsernamePasswordAuthenticationToken(loginParams.getUsername(), loginParams.getPassword()));
//                authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
            catch (Exception e)
            {
                if (e instanceof BadCredentialsException)
                {
                    AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginParams.getUsername(), Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                    throw new UserPasswordNotMatchException();
                }
                else
                {
                    AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginParams.getUsername(), Constants.LOGIN_FAIL, e.getMessage()));
                    throw new ServiceException(e.getMessage());
                }
            }
        }


        LoginUser loginUser = (LoginUser) authentication.getPrincipal();

        SysUser user = loginUser.getUser();
        SysUserCid sysUserCid = new SysUserCid();
        sysUserCid.setCid(loginParams.getCid());
        sysUserCid.setUserId(user.getUserId());


                if(loginParams.getRegisterFlag() == 1){
                    sysUserCidMapper.insertSysUserCid(sysUserCid);
                }
                else {
                    sysUserCidMapper.updateSysUserCid(sysUserCid);
                }
        AjaxResult ajax = AjaxResult.success("");

        Long teacherId = sysTeacherUserMapper.selectSysTeacherUserByUserId(user.getUserId());
        if (teacherId != null){
            ajax.put("teacherId",teacherId);
        }
        else {
            List<Student> students = studentMapper.selectUserStudentList(user.getUserId());
            ajax.put("studentArray",students);
        }

        // 生成token
        String token = tokenService.createToken(loginUser);
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginParams.getUsername(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        sysLoginService.recordLoginInfo(user.getUserId());
        //判断用户是否存在管理员角色
        // 角色集合
//        Set<String> roles = permissionService.getRolePermission(user);
//        boolean roleFlag = false;
//        if(!CollectionUtils.isEmpty(roles)){
//            for (String roleKey : roles) {
//                if(roleKey.equals("agent")){
//                    roleFlag = true;
//                    break;
//                }
//            }
//        }
        ajax.put("token",token);

        //token过期时间
        ajax.put("expired",loginUser.getExpireTime());
        ajax.put("user",loginUser.getUser());
        ajax.put("isAgent",String.valueOf(true));


        return ajax;
    }
    /**
     * 发送注册验证码
     * @param loginParams
     * @return
     */
    public AjaxResult   sendCode(LoginParams loginParams) throws Exception {
        if (Objects.isNull(loginParams)) {
            return AjaxResult.error(-6,"参数为空");
        }
        // 验证验证码
        if ( StringUtils.isBlank(loginParams.getPhoneNo())) {
            return AjaxResult.error(-6,"发送手机号不能为空");
        }
//        String validCodeType = "2";
//        if (StringUtils.isNotBlank(loginParams.getValidCodeType())) {
//            validCodeType = loginParams.getValidCodeType();
//        }
        try{
            //SysSmsSend sysSmsSend = sysSmsSendService.sendMessage(loginParams.getPhoneNo(),validCodeType,true);
            //String resultFlag = sysSmsSend.getResultFlag();
            if(StringUtils.isBlank(loginParams.getValidCode())){
                return AjaxResult.error(-6,"验证码发送失败");
            }
            if(sysUserMapper.selectUserByUserName(loginParams.getPhoneNo())!=null && loginParams.getValidCodeType().equals("1")

            ){
                return AjaxResult.error(-6,"该手机号已经注册");
            }
        }catch (Exception e){
            throw new ServiceException(e.getMessage());
        }
        String codeKey= "";
//        SMSUtils.sendMessage("蒙爱教育","SMS_154950909",loginParams.getPhoneNo(),loginParams.getValidCode());
        if (loginParams.getValidCodeType().equals("0")){
             codeKey= CacheConstants.PHONE_LOGIN_CODE_KEY+loginParams.getPhoneNo();
        }
        else if (loginParams.getValidCodeType().equals("1")){
            codeKey= CacheConstants.PHONE_REGISTER_CODE_KEY+loginParams.getPhoneNo();

        }
        else if (loginParams.getValidCodeType().equals("2")){
             codeKey= CacheConstants.PHONE_FORGET_CODE_KEY+loginParams.getPhoneNo();


        }
        if (!redisCache.hasKey(codeKey)){
            System.out.println(codeKey+"验证码"+loginParams.getValidCode());
            redisCache.setCacheObject(codeKey, loginParams.getValidCode(), 5, TimeUnit.MINUTES);
        }

       else{
           return  AjaxResult.error(-6,"请勿重新发送验证码");
        }

        AjaxResult ajax = AjaxResult.success("验证码发送成功");
        return ajax;
    }
    /**
     * 手机号验证码注册用户
     * @param loginParams
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult forget(LoginParams loginParams) {
        try{
            if (Objects.isNull(loginParams)) {
                return AjaxResult.error(-6,"参数为空");
            }
            String phoneNo = loginParams.getPhoneNo();
            if (StringUtils.isBlank(phoneNo)) {
                return AjaxResult.error(-6,"发送手机号不能为空");
            }
            String codeKey= CacheConstants.PHONE_FORGET_CODE_KEY+loginParams.getPhoneNo();
            String codeSession =(String) redisCache.getCacheObject(codeKey);
            //从session中获得保存到的验证码
            String validCode = loginParams.getValidCode();
            if (StringUtils.isBlank(validCode)) {
                return AjaxResult.error(-6,"验证码不能为空");
            }
            if (!codeSession.equals(validCode)) {
                return AjaxResult.error(-6,"验证码错误");
            }
            SysUser sysUser = new SysUser();
            sysUser.setUserName(loginParams.getPhoneNo());

            sysUser.setPassword(SecurityUtils.encryptPassword(loginParams.getPassword()));

            sysUserMapper.updatePhonenumberUser(sysUser);
            return  AjaxResult.success("修改密码成功");
        }catch (Exception e){
            throw new ServiceException(e.getMessage());
        }
    }
    /**
     * 手机号验证码注册用户
     * @param loginParams
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult registerUser(LoginParams loginParams) {
        try{
            if (Objects.isNull(loginParams)) {
                return AjaxResult.error(-6,"参数为空");
            }
            String phoneNo = loginParams.getPhoneNo();
            if (StringUtils.isBlank(phoneNo)) {
                return AjaxResult.error(-6,"发送手机号不能为空");
            }
            String codeKey= CacheConstants.PHONE_REGISTER_CODE_KEY+loginParams.getPhoneNo();
            String codeSession =(String) redisCache.getCacheObject(codeKey);
            System.out.println(codeSession);
            //从session中获得保存到的验证码
            String validCode = loginParams.getValidCode();
            if (StringUtils.isBlank(validCode)) {
                return AjaxResult.error(-6,"验证码不能为空");
            }
            if (!codeSession.equals(validCode)) {
                return AjaxResult.error(-6,"验证码错误");
            }

            loginParams.setUsername(phoneNo);
//            loginParams.setPassword(loginParams.getPassword());
            loginParams.setLoginType("1");
            return  this.register(loginParams);
        }catch (Exception e){
            throw new ServiceException(e.getMessage());
        }
    }
    /**
     * 注册
     */
    public AjaxResult register(LoginParams registerBody)
    {
        String username = registerBody.getUsername(), password = registerBody.getPassword(),status=registerBody.getValidCodeType();
        SysUser sysUser = new SysUser();
        sysUser.setUserName(username);
        sysUser.setStatus(status);
//        sysUser.setDelFlag();


        if (StringUtils.isEmpty(username))
        {
            return AjaxResult.error(-6,"用户名不能为空");
        }
        else if (StringUtils.isEmpty(password))
        {
            return AjaxResult.error(-6,"密码不能为空");
        }

        else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
        {
            return AjaxResult.error(-6,"密码长度必须在5到20个字符之间");
        }
        else if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(sysUser)))
        {
            return AjaxResult.error(-6,"保存用户'" + username + "'失败，注册账号已存在");
        }
        else
        {
            sysUser.setNickName(username);
            sysUser.setPassword(SecurityUtils.encryptPassword(password));
            boolean regFlag = userService.registerUser(sysUser);
            if (!regFlag)
            {
                return AjaxResult.error(-6,"注册失败,请联系系统管理人员");
            }
            SysUserRole sysUserRole = new SysUserRole();
            if (status.equals("0")){
                sysUserRole.setRoleId(101L);
            }
            else if (status.equals("1")){
                sysUserRole.setRoleId(102L);
            }

            sysUserRole.setUserId(sysUser.getUserId());
            int regCount = sysUserRoleMapper.insertUserRole(sysUserRole);
            if (regCount <=0)
            {
                return AjaxResult.error(-6,"注册失败,请联系系统管理人员");
            }
            else
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success")));
            }
        }
        if (status.equals("1")){
            SysUserCid sysUserCid = new SysUserCid();
            sysUserCid.setCid(registerBody.getCid());
            sysUserCid.setUserId(sysUser.getUserId());
            sysUserCidMapper.insertSysUserCid(sysUserCid);
            return  AjaxResult.success("注册成功");
        }
        registerBody.setRegisterFlag(1);
        return  login(registerBody);
    }


    /**
     * 设置注册用户角色部门岗位信息
     * @param registerUser
     * @return
     */
    private void setUserDefaultInfo(SysUser registerUser ){
        String registerRoleCode = DictUtils.getDictValue("sys_config","register_role_code","");
        if (StringUtils.isBlank(registerRoleCode)) {
            throw new ServiceException("请前往数据字典【sys_config】中维护注册用户角色编码【register_role_code】");
        }
        String registerDeptCode = DictUtils.getDictValue("sys_config","register_dept_code","");
        if (StringUtils.isBlank(registerDeptCode)) {
            throw new ServiceException("请前往数据字典【sys_config】中维护注册用户部门编码【register_dept_code】");
        }
        String registerPostCode = DictUtils.getDictValue("sys_config","register_post_code","");
        if (StringUtils.isBlank(registerPostCode)) {
            throw new ServiceException("请前往数据字典【sys_config】中维护注册用户岗位编码【register_post_code】");
        }

    }

}
